﻿#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qprintermanager.h"
#include "worker.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    showMaximized();
    serialPort = new QSerialPort;

    InitialSetting();
    InitChart();
    m_ptimer = new QTimer(this);
    connect(m_ptimer,&QTimer::timeout,this,&MainWindow::slotTimeOut);

    workerThread = new Worker();
    connect(workerThread, &Worker::resultReady, this, &MainWindow::handleResults);
    connect(workerThread, &Worker::finished, workerThread, &QObject::deleteLater);
}

MainWindow::~MainWindow()
{
    delete ui;
    workerThread->setStop();
}

//实现软件参变量的初始化设定
void MainWindow::InitialSetting()
{
    //填充串口号组合框
    SearchSerialPorts();

    //填充串口波特率
    ui->comboBoxBaud->addItem("9600");
    ui->comboBoxBaud->addItem("14400");
    ui->comboBoxBaud->addItem("19200");
    ui->comboBoxBaud->addItem("28800");
    ui->comboBoxBaud->addItem("38400");
    ui->comboBoxBaud->addItem("56000");
    ui->comboBoxBaud->addItem("57600");
    ui->comboBoxBaud->addItem("115200");
    ui->comboBoxBaud->addItem("128000");
    ui->comboBoxBaud->addItem("230400");
    ui->comboBoxBaud->addItem("256000");
    ui->comboBoxBaud->setCurrentIndex(7);

    //填充串口数据位
    ui->comboBoxData->addItem(QStringLiteral("7位"));
    ui->comboBoxData->addItem(QStringLiteral("8位"));
    ui->comboBoxData->addItem(QStringLiteral("9位"));
    ui->comboBoxData->setCurrentIndex(1);

    //填充串口校验位
    ui->comboBoxParity->addItem(QStringLiteral("无校验"));
    ui->comboBoxParity->addItem(QStringLiteral("奇校验"));
    ui->comboBoxParity->addItem(QStringLiteral("偶校验"));

    //填充串口停止位
    ui->comboBoxStop->addItem(QStringLiteral("1位"));
    ui->comboBoxStop->addItem(QStringLiteral("1.5位"));
    ui->comboBoxStop->addItem(QStringLiteral("2位"));

    //为变量赋初值
    receivedBytes=0;
    transmitBytes=0;
    snIndex=1;
    ui->lineEdit_17->setText(QDateTime::currentDateTime().toString("yyyyMMddhhmmss"));
    ui->dateEdit->setDate(QDate::currentDate());
}

//搜索可用的串口，并添加到串口组合框
void MainWindow::SearchSerialPorts()
{
    ui->comboBoxPort->clear();

    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        ui->comboBoxPort->addItem(info.portName());
    }
}

void MainWindow::InitChart()
{
    //初始化QChart的实例
    m_pChart = new QChart();
    //初始化QSplineSeries的实例
    m_pSer0 = new QSplineSeries();
    m_pSer1 = new QSplineSeries();
    m_pSer2 = new QSplineSeries();
    //设置曲线的名称
    QPen pen;
    m_pSer0->setName(QStringLiteral("中心温度"));
    pen.setColor(QColor(255,0,0));
    pen.setWidth(3);
    m_pSer0->setPen(pen);
    m_pSer1->setName(QStringLiteral("表面温度"));
    pen.setColor(QColor(230, 126, 34));
    pen.setWidth(5);
    m_pSer1->setPen(pen);
    m_pSer2->setName(QStringLiteral("炉内温度"));
    pen.setColor(QColor(0,255,0));
    pen.setWidth(3);
    m_pSer2->setPen(pen);
    //把曲线添加到QChart的实例chart中
    m_pChart->addSeries(m_pSer0);
    m_pChart->addSeries(m_pSer1);
    m_pChart->addSeries(m_pSer2);
    //声明并初始化X轴、两个Y轴
    QValueAxis *axisX = new QValueAxis();
    QValueAxis *axisY = new QValueAxis();
    //设置坐标轴显示的范围
    axisX->setMin(0);
    axisX->setMax(MAX_X);
    axisY->setMin(650);
    axisY->setMax(MAX_Y);
    //设置坐标轴上的格点
    axisX->setTickCount(13);
    axisY->setTickCount(8);
    //设置坐标轴显示的名称
    QFont font("Microsoft YaHei",8,QFont::Normal);//微软雅黑。字体大小8
    axisX->setTitleFont(font);
    axisY->setTitleFont(font);
    axisX->setTitleText(QStringLiteral("时间(min)"));
    axisY->setTitleText(QStringLiteral("温度(℃)"));
    //设置网格不显示
    //axisY->setGridLineVisible(false);
    //下方：Qt::AlignBottom，左边：Qt::AlignLeft
    //右边：Qt::AlignRight，上方：Qt::AlignTop
    m_pChart->addAxis(axisX, Qt::AlignBottom);
    m_pChart->addAxis(axisY, Qt::AlignLeft);
    //把曲线关联到坐标轴
    m_pSer0->attachAxis(axisX);
    m_pSer0->attachAxis(axisY);
    m_pSer1->attachAxis(axisX);
    m_pSer1->attachAxis(axisY);
    m_pSer2->attachAxis(axisX);
    m_pSer2->attachAxis(axisY);
    //把chart显示到窗口上
    ui->graphicsView->setChart(m_pChart);
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);      // 设置渲染：抗锯齿，如果不设置那么曲线就显得不平滑
}

void MainWindow::SaveChart2Image()
{
    QPixmap pix = ui->graphicsView->grab();
    QImage image = pix.toImage();
    //image = image.scaled(600, 381);
    image.save(QCoreApplication::applicationDirPath()+"/4.png");
}

//从串口接收数据
void MainWindow::ReadSerialData()
{
    QByteArray context = serialPort->readAll().toHex();
    ui->plainTextEdit_2->appendPlainText(context);
    workerThread->appendData(context);
}

void MainWindow::on_actionprint_triggered()
{
    QPrinterManager PM;
    PM.dataBegin();
    PM.insertTitle(QStringLiteral("建材不燃性材料报告"));
    PM.insertSeperator();
    QList<QPair<QString,QString>> columnList;
    columnList.append(qMakePair(QStringLiteral("测试编号"),ui->lineEdit_17->text()));
    columnList.append(qMakePair(QStringLiteral("送检公司"),ui->lineEdit_18->text()));
    columnList.append(qMakePair(QStringLiteral("检测单位"),ui->lineEdit_19->text()));
    columnList.append(qMakePair(QStringLiteral("报告日期"),ui->dateEdit->text()));
    columnList.append(qMakePair(QStringLiteral("测试人员"),ui->lineEdit_20->text()));
    PM.insert2table(columnList);
    PM.tableEnd();

    PM.insertTitle2(QStringLiteral("材料说明:%1").arg(ui->plainTextEdit->toPlainText()));
    QList<QPair<QString,QString>> columnList2;
    columnList2.append(qMakePair(QStringLiteral("炉内最高温度:%1℃").arg(ui->lineEdit_6->text()),QStringLiteral("炉内初始温度:%1℃").arg(ui->lineEdit_9->text())));
    columnList2.append(qMakePair(QStringLiteral("炉内最终温度:%1℃").arg(ui->lineEdit_7->text()),QStringLiteral("材料燃烧时间:%1S").arg(ui->lineEdit_10->text())));
    columnList2.append(qMakePair(QStringLiteral("炉内     温升:%1℃").arg(ui->lineEdit_8->text()),QStringLiteral("燃烧质量损失:%1%").arg(ui->lineEdit_21->text())));
    PM.insert3table(columnList2);
    PM.tableEnd();
    if(ui->checkBox_2->isChecked())
    {
        PM.insertSeperator();
        PM.insertTitle2(QStringLiteral(""));
        QList<QPair<QString,QString>> columnList3;
        columnList3.append(qMakePair(QStringLiteral("表面最高温度:%1℃").arg(ui->lineEdit_11->text()),QStringLiteral("中心最高温度:%1℃").arg(ui->lineEdit_14->text())));
        columnList3.append(qMakePair(QStringLiteral("表面最终温度:%1℃").arg(ui->lineEdit_12->text()),QStringLiteral("中心最终温度:%1℃").arg(ui->lineEdit_15->text())));
        columnList3.append(qMakePair(QStringLiteral("表面     温升:%1℃").arg(ui->lineEdit_13->text()),QStringLiteral("中心     温升:%1℃").arg(ui->lineEdit_16->text())));
        PM.insert3table(columnList3);
        PM.tableEnd();
        PM.insertSeperator();
    }
    if(ui->checkBox_3->isChecked())
    {
        SaveChart2Image();
        PM.insertChart(QCoreApplication::applicationDirPath()+"/4.png");
    }
    PM.dataEnd();
    PM.printWithPreview();
}

void MainWindow::slotTimeOut()
{
    if(num >= 6)
    {
        num = 0;
        m_pSer0->append(count/10.0, ZXtemp);
        m_pSer1->append(count/10.0, BMtemp);
        m_pSer2->append(count/10.0, LNtemp);
        count++;
    }
    num++;
}

void MainWindow::handleResults(const QString &str, double value)
{
    if(str == "00")
    {
        ZXtemp = value;
        ui->lineEdit->setText(QString::number(value));
    }
    else if(str == "01")
    {
        BMtemp = value;
        ui->lineEdit_2->setText(QString::number(value));
    }
    else if(str == "02")
    {
        LNtemp = value;
        ui->lineEdit_3->setText(QString::number(value));
    }
    else if(str == "03")
    {
        ui->lineEdit_4->setText(QString::number(value));
    }
    else if(str == "04")
    {
        ui->lineEdit_5->setText(QString::number(value));
    }
    else if(str == "05")
    {
        ui->lineEdit_6->setText(QString::number(value));
    }
    else if(str == "06")
    {
        ui->lineEdit_7->setText(QString::number(value));
    }
    else if(str == "07")
    {
        ui->lineEdit_8->setText(QString::number(value));
    }
    else if(str == "08")
    {
        ui->lineEdit_11->setText(QString::number(value));
    }
    else if(str == "09")
    {
        ui->lineEdit_12->setText(QString::number(value));
    }
    else if(str == "0a")
    {
        ui->lineEdit_13->setText(QString::number(value));
    }
    else if(str == "0b")
    {
        ui->lineEdit_14->setText(QString::number(value));
    }
    else if(str == "0c")
    {
        ui->lineEdit_15->setText(QString::number(value));
    }
    else if(str == "0d")
    {
        ui->lineEdit_16->setText(QString::number(value));
    }
    else if(str == "0e")
    {
        ui->lineEdit_9->setText(QString::number(value));
    }
    else if(str == "0f")
    {
        ui->lineEdit_10->setText(QString::number(value));
    }
    else if(str == "10")
    {
        ui->plainTextEdit_2->appendPlainText(QStringLiteral("收到开始消息"));
        //清空界面
        ui->lineEdit->setText("0");
        ui->lineEdit_2->setText("0");
        ui->lineEdit_3->setText("0");
        ui->lineEdit_4->setText("0");
        ui->lineEdit_5->setText("0");
        ui->lineEdit_6->setText("0");
        ui->lineEdit_9->setText("0");
        ui->lineEdit_7->setText("0");
        ui->lineEdit_10->setText("0");
        ui->lineEdit_8->setText("0");
        ui->lineEdit_11->setText("0");
        ui->lineEdit_14->setText("0");
        ui->lineEdit_12->setText("0");
        ui->lineEdit_15->setText("0");
        ui->lineEdit_13->setText("0");
        ui->lineEdit_16->setText("0");
        ui->lineEdit_21->setText("0");
        ui->plainTextEdit->setPlainText("");
        QVector<QPointF> points;//清空然后replace
        m_pSer0->replace(points); //利用replace函数更新数据
        m_pSer1->replace(points); //利用replace函数更新数据
        m_pSer2->replace(points); //利用replace函数更新数据
        //开始
        workerThread->clearData();
        m_ptimer->start(1000);
        num = 0;
        count = 0;
    }
    else if(str == "11")
    {
        ui->plainTextEdit_2->appendPlainText(QStringLiteral("收到结束消息"));
        workerThread->clearData();
        m_ptimer->stop();
    }
}

//退出软件
void MainWindow::on_actionExit_triggered()
{
    this->close();
}

//打开串口
void MainWindow::on_actionConnect_triggered()
{
    serialPort->setPortName(ui->comboBoxPort->currentText());

    if(serialPort->open(QIODevice::ReadWrite))              //打开串口成功
    {
        serialPort->setBaudRate(ui->comboBoxBaud->currentText().toInt());       //设置波特率

        switch(ui->comboBoxData->currentIndex())                   //设置数据位数
        {
        case 1:serialPort->setDataBits(QSerialPort::Data8);break;
        default: break;
        }

        switch(ui->comboBoxParity->currentIndex())                   //设置奇偶校验
        {
        case 0: serialPort->setParity(QSerialPort::NoParity);break;
        default: break;
        }

        switch(ui->comboBoxStop->currentIndex())                     //设置停止位
        {
        case 1: serialPort->setStopBits(QSerialPort::OneStop);break;
        case 2: serialPort->setStopBits(QSerialPort::TwoStop);break;
        default: break;
        }

        serialPort->setFlowControl(QSerialPort::NoFlowControl);     //设置流控制

        //连接槽函数
        QObject::connect(serialPort, &QSerialPort::readyRead, this, &MainWindow::ReadSerialData);

        // 设置控件可否使用
        ui->actionConnect->setEnabled(false);
        ui->actionClose->setEnabled(true);
        ui->actionRefresh->setEnabled(false);
        //清空界面
        ui->lineEdit->setText("0");
        ui->lineEdit_2->setText("0");
        ui->lineEdit_3->setText("0");
        ui->lineEdit_4->setText("0");
        ui->lineEdit_5->setText("0");
        ui->lineEdit_6->setText("0");
        ui->lineEdit_9->setText("0");
        ui->lineEdit_7->setText("0");
        ui->lineEdit_10->setText("0");
        ui->lineEdit_8->setText("0");
        ui->lineEdit_11->setText("0");
        ui->lineEdit_14->setText("0");
        ui->lineEdit_12->setText("0");
        ui->lineEdit_15->setText("0");
        ui->lineEdit_13->setText("0");
        ui->lineEdit_16->setText("0");
        ui->lineEdit_21->setText("0");
        ui->plainTextEdit->setPlainText("");
        workerThread->setStart();
    }
    else    //打开失败提示
    {
        QMessageBox::information(this,QStringLiteral("错误"),QStringLiteral("打开串口失败！"),QMessageBox::Ok);
    }
}

//关闭串口
void MainWindow::on_actionClose_triggered()
{
    serialPort->clear();
    serialPort->close();

    // 设置控件可否使用
    ui->actionConnect->setEnabled(true);
    ui->actionClose->setEnabled(false);
    ui->actionRefresh->setEnabled(true);

    workerThread->clearData();
    m_ptimer->stop();
    num = 0;
    count = 0;
}

//刷新串口列表
void MainWindow::on_actionRefresh_triggered()
{
    //填充串口号组合框
    SearchSerialPorts();
}

//保存数据
void MainWindow::on_actionsave_triggered()
{
    if(serialPort->isOpen())
    {
        QMessageBox::information(this,QStringLiteral("错误"),QStringLiteral("保存数据前请关闭串口！"),QMessageBox::Ok);
        return;
    }
    QString fileName = QFileDialog::getSaveFileName(this,QStringLiteral("文本对话框"),"",QStringLiteral("Config Files (*.txt)"));
    QFile file(fileName);

    if(!file.open(QIODevice::WriteOnly|QIODevice::Text))
    {
        return;
    }
    QTextStream stream(&file);
    stream<<ui->lineEdit_17->text()+"\n";
    stream<<ui->lineEdit_18->text()+"\n";
    stream<<ui->lineEdit_19->text()+"\n";
    stream<<ui->dateEdit->text()+"\n";
    stream<<ui->lineEdit_20->text()+"\n";
    stream<<ui->lineEdit_6->text()+"\n";
    stream<<ui->lineEdit_9->text()+"\n";
    stream<<ui->lineEdit_7->text()+"\n";
    stream<<ui->lineEdit_10->text()+"\n";
    stream<<ui->lineEdit_8->text()+"\n";
    stream<<ui->lineEdit_11->text()+"\n";
    stream<<ui->lineEdit_14->text()+"\n";
    stream<<ui->lineEdit_12->text()+"\n";
    stream<<ui->lineEdit_15->text()+"\n";
    stream<<ui->lineEdit_13->text()+"\n";
    stream<<ui->lineEdit_16->text()+"\n";
    stream<<ui->lineEdit_21->text()+"\n";
    stream<<ui->plainTextEdit->toPlainText()+"\n";

    QList<QPointF> points = m_pSer0->points();
    for(auto item : points)
    {
        stream<<item.x() << ","<< item.y();
        stream<<"&";
    }
    stream<<"\n";

    points = m_pSer1->points();
    for(auto item : points)
    {
        stream<<item.x() << ","<< item.y();
        stream<<"&";
    }
    stream<<"\n";

    points = m_pSer2->points();
    for(auto item : points)
    {
        stream<<item.x() << ","<< item.y();
        stream<<"&";
    }
    stream<<"\n";

    file.close();
    QMessageBox::information(this,QStringLiteral("提示"),QStringLiteral("保存成功！"),QMessageBox::Ok);
}

void MainWindow::on_actionread_triggered()
{
    std::vector<QString> strs;
    if(serialPort->isOpen())
    {
        QMessageBox::information(this,QStringLiteral("错误"),QStringLiteral("读取数据前请关闭串口！"),QMessageBox::Ok);
        return;
    }
    QString fileName = QFileDialog::getOpenFileName(this,QStringLiteral("文本对话框"),"",QStringLiteral("*.txt"));
    QFile file(fileName);

    if(!file.open(QIODevice::ReadOnly))
    {
        return;
    }

    QTextStream stream(&file);

    while(!stream.atEnd())
    {
        QString line = stream.readLine();
        strs.push_back(line);
    }

    file.close();
    if(strs.size() == 21)
    {
        QMessageBox::information(this,QStringLiteral("提示"),QStringLiteral("读取成功！"),QMessageBox::Ok);
        ui->lineEdit_17->setText(strs.at(0));
        ui->lineEdit_18->setText(strs.at(1));
        ui->lineEdit_19->setText(strs.at(2));
        ui->dateEdit->setDate(QDate::fromString(strs.at(3),"yyyy/M/d"));
        ui->lineEdit_20->setText(strs.at(4));
        ui->lineEdit_6->setText(strs.at(5));
        ui->lineEdit_9->setText(strs.at(6));
        ui->lineEdit_7->setText(strs.at(7));
        ui->lineEdit_10->setText(strs.at(8));
        ui->lineEdit_8->setText(strs.at(9));
        ui->lineEdit_11->setText(strs.at(10));
        ui->lineEdit_14->setText(strs.at(11));
        ui->lineEdit_12->setText(strs.at(12));
        ui->lineEdit_15->setText(strs.at(13));
        ui->lineEdit_13->setText(strs.at(14));
        ui->lineEdit_16->setText(strs.at(15));
        ui->lineEdit_21->setText(strs.at(16));
        ui->plainTextEdit->setPlainText(strs.at(17));

        QVector<QPointF> points;//清空然后replace
        m_pSer0->replace(points); //利用replace函数更新数据
        m_pSer1->replace(points); //利用replace函数更新数据
        m_pSer2->replace(points); //利用replace函数更新数据

        QVector<QPointF> aa;
        for(auto item : strs[18].split('&'))
        {
            if(item.split(',').size() == 2)
            {
                QPointF point(item.split(',').at(0).toDouble(),item.split(',').at(1).toDouble());
                aa.append(point);
            }
        }
        m_pSer0->replace(aa); //利用replace函数更新数据

        QVector<QPointF> bb;
        for(auto item : strs[19].split('&'))
        {
            if(item.split(',').size() == 2)
            {
                QPointF point(item.split(',').at(0).toDouble(),item.split(',').at(1).toDouble());
                bb.append(point);
            }
        }
        m_pSer1->replace(bb); //利用replace函数更新数据

        QVector<QPointF> cc;
        for(auto item : strs[20].split('&'))
        {
            if(item.split(',').size() == 2)
            {
                QPointF point(item.split(',').at(0).toDouble(),item.split(',').at(1).toDouble());
                cc.append(point);
            }
        }
        m_pSer2->replace(cc); //利用replace函数更新数据
    }
    else
    {
        QMessageBox::information(this,QStringLiteral("提示"),QStringLiteral("读取失败！"),QMessageBox::Ok);
    }

}
